<?php

namespace App\Http\Controllers;

use App\Models\Player;
use App\Models\User;
use App\Rules\UrlSignature;
use EasyWeChat\Kernel\Exceptions\InvalidArgumentException;
use Exception;
use Illuminate\Contracts\View\View;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;

class AuthController extends Controller
{
    /**
     * Notes   : 发起微信授权，跳转到微信授权页面
     *
     * @Date   : 2024/7/17 下午2:47
     * @Author : <Jason.C>
     * @param  Request  $request
     * @return View|RedirectResponse
     * @throws InvalidArgumentException
     */
    public function index(Request $request)
    {
        try {
            $this->checkWechatAgent($request);
            $this->checkRequestParams($request);
            $this->initApplication($request);
        } catch (Exception $exception) {
            return $this->showError($exception->getMessage());
        }

        $player = Player::find($request->player_id);

        if ($player->isDisabled() || $this->application->isNot($player->application)) {
            return $this->showError('选手不存在');
        }

        $oauth = $player->chapter->initWechat()->getOAuth();

        $redirect = route('auth.wechat.token.callback', [
            'callback' => $request->callback,
            'app_key' => $request->app_key,
            'player_id' => $request->player_id,
        ]);

        $authUrl = $oauth->scopes(['snsapi_userinfo'])->redirect($redirect);

        return redirect()->away($authUrl);
    }

    /**
     * Notes   : 参数检测
     *
     * @Date   : 2024/7/19 下午2:18
     * @Author : <Jason.C>
     * @param  Request  $request
     * @throws Exception
     */
    protected function checkRequestParams(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'callback' => 'required|bail|url',
            'app_key' => 'required|bail|exists:App\Models\Application,app_key',
            'player_id' => 'required|bail|exists:App\Models\Player,id',
            'signature' => [
                'required',
                'bail',
                'string',
                new UrlSignature,
            ],
        ], [
            'callback.required' => '回调地址不能为空',
            'callback.url' => '回调地址格式不正确',
            'app_key.required' => '应用标识不能为空',
            'app_key.exists' => '应用标识不存在',
            'player_id.required' => '参数错误',
            'player_id.exists' => '参数错误',
            'signature.required' => '签名错误',
            'signature.string' => '签名错误',
        ]);

        if ($validator->fails()) {
            throw new Exception($validator->errors()->first());
        }
    }

    /**
     * Notes   : 授权结果回调
     *
     * @Date   : 2024/7/18 下午5:27
     * @Author : <Jason.C>
     * @param  Request  $request
     * @return View|RedirectResponse
     */
    public function callback(Request $request)
    {
        try {
            $this->initApplication($request);
        } catch (Exception $exception) {
            return $this->showError($exception->getMessage());
        }

        try {
            $player = Player::find($request->player_id);

            if ($player->isDisabled() || $this->application->isNot($player->application)) {
                return $this->showError('选手不存在');
            }

            $oauth = $player->chapter->initWechat()->getOAuth();
            $user = $oauth->userFromCode($request->get('code'));

            $user = User::updateOrCreate([
                'application_id' => $this->application->id,
                'wechat_id' => $player->getWechatId(),
                'openid' => $user->getId(),
            ], [
                'nickname' => $user->getNickname(),
                'avatar' => $user->getAvatar(),
            ]);

            $token = $user->createToken($this->application->app_key)->plainTextToken;

            return redirect()->away($request->callback.'?token='.base64_encode($token));
        } catch (Exception $exception) {
            return redirect()->away($request->callback.'?error='.$exception->getMessage());
        }
    }
}
